package week01

// 641. 设计循环双端队列
// https://leetcode-cn.com/problems/design-circular-deque/

// 1、计算 Head 时，注意加上 List 的长度，防止 Head 等于负数
// 2、InsertLast 计算的是 tail+1， GetRear 计算的是 tail

type MyCircularDeque struct {
	List []int
	Head int
	Length int
}


/** Initialize your data structure here. Set the size of the deque to be k. */
func Constructor(k int) MyCircularDeque {
	return MyCircularDeque{
		List: make([]int, k),
	}
}


/** Adds an item at the front of Deque. Return true if the operation is successful. */
func (this *MyCircularDeque) InsertFront(value int) bool {
	if this.IsFull() {
		return false
	}
	this.Head = (this.Head + len(this.List) - 1) % len(this.List)
	this.List[this.Head] = value
	this.Length++
	return true
}


/** Adds an item at the rear of Deque. Return true if the operation is successful. */
func (this *MyCircularDeque) InsertLast(value int) bool {
	if this.IsFull() {
		return false
	}
	tail := (this.Head + this.Length + len(this.List)) % len(this.List)
	this.List[tail] = value
	this.Length++
	return true
}


/** Deletes an item from the front of Deque. Return true if the operation is successful. */
func (this *MyCircularDeque) DeleteFront() bool {
	if this.IsEmpty() {
		return false
	}
	this.Head++
	this.Head = this.Head % len(this.List)
	this.Length--
	return true
}


/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
func (this *MyCircularDeque) DeleteLast() bool {
	if this.IsEmpty() {
		return false
	}
	this.Length--
	return true
}


/** Get the front item from the deque. */
func (this *MyCircularDeque) GetFront() int {
	if this.IsEmpty() {
		return -1
	}
	return this.List[this.Head]
}


/** Get the last item from the deque. */
func (this *MyCircularDeque) GetRear() int {
	if this.IsEmpty() {
		return -1
	}
	tail := (this.Head + this.Length + len(this.List) - 1) % len(this.List)
	return this.List[tail]
}


/** Checks whether the circular deque is empty or not. */
func (this *MyCircularDeque) IsEmpty() bool {
	return this.Length == 0
}


/** Checks whether the circular deque is full or not. */
func (this *MyCircularDeque) IsFull() bool {
	return len(this.List) == this.Length
}